import common from '../../dxmodules/dxCommon.js'
import log from '../../dxmodules/dxLogger.js'
import config from '../../dxmodules/dxConfig.js'
import CryptoES from '../../dxmodules/crypto-es/index.js';
import driver from '../driver.js'
const nfcService = {}
nfcService.receiveMsg = function (data) {
    log.info('[nfcService] receiveMsg:' + JSON.stringify(data))
    let nfcType = config.get("sysInfo.nfcType")
    let sectorNumber = config.get('sysInfo.sectorNumber')
    let blockNumber = config.get('sysInfo.blockNumber')
    let cardId = ""
    if (data.card_type && data.id) {
        if (sectorNumber !== "" && blockNumber !== "") {
            if(data.card_type == 66 || data.card_type == 76) {
                // Standard Card/Encrypted Card: Fixed sector, one card, one key
                let secretkey = config.get('sysInfo.secretkey')
                let keyType = config.get('sysInfo.secretkeyType')
                if (nfcType == 3) {
                    let md5 = CryptoES.MD5(`${(data.id).toUpperCase()}${secretkey}`).toString(CryptoES.enc.Hex)
                    let hmac = CryptoES.HmacMD5(md5, md5.slice(0, 16)).toString(CryptoES.enc.Hex)
                    secretkey = `${hmac.slice(-6)}000000`
                }
                let secretkeyArr = secretkey.match(/.{1,2}/g).map(item => '0x' + item)
                let secretkeyType = keyType == 1 ? 0x60 : 0x61
                let cardArray = driver.nfc.m1cardReadSector(0, sectorNumber, blockNumber, 1, secretkeyArr, secretkeyType)
                if (cardArray) {
                    let code = common.uint8ArrayToHexString(cardArray).substring(0, 8)
                    if (nfcType == 1 || nfcType == 2) {
                        cardId = code
                    } else {
                        cardId = code == data.id ? code : ""
                    }
                }
            }
        } else {
            cardId = data.id
        }
    }
    if (!cardId) {
        let tipMsg = config.get("sysInfo.language") == 1 ? "Card reading failed" : "Card reading failed"
        driver.screen.customPopWin(tipMsg, 3000, undefined, false)
        driver.pwm.fail()
        return
    }
    //positive and negative
    if (config.get("sysInfo.ord") == 1) {
        cardId = cardId.match(/.{2}/g).reverse().join('')
    }
    // Start bit, counted in bytes
    let st = config.get("sysInfo.st")
    // Output length, in bytes
    let len = config.get("sysInfo.len")
    if (cardId.length == 8) {
        //4. Direct Card Number Processing Logic
        cardId = fourHandle(cardId, st, len)
    } else {
        //Other processing logic
        cardId = cardId.substring((st - 1) * 2, len * 2)
    }
    // Output format
    let nft = parseInt(config.get("sysInfo.nft"))
    if (nft == 0) {
        if (cardId.length % 2 != 0) {
            cardId = '0' + cardId
        }
    } else if (nft == 1) {
        cardId = common.stringToHex(cardId)
    } else if (nft == 2) {
        let parseIntCardId = BigInt('0x' + cardId).toString().padStart(10, '0')
        cardId = common.stringToHex(parseIntCardId)
    }
    // Prefixes and suffixes
    let pri = config.get("sysInfo.pri")
    let pos = config.get("sysInfo.pos")
    if (config.get("sysInfo.horc") == 1) {
        if (!isHexadecimal(pri) || pri.length % 2 != 0) {
            pri = ""
        }
        if (!isHexadecimal(pos) || pos.length % 2 != 0) {
            pos = ""
        }
    } else {
        pri = common.stringToHex(pri)
        pos = common.stringToHex(pos)
    }

    cardId = pri + cardId
    cardId += pos

    if (config.get("sysInfo.nnl") == 1) {
        cardId += "0D"
    }
    if (config.get("sysInfo.ncr") == 1) {
        cardId += "0A"
    }
    cardId = cardId

    // Actions after swiping the card
    let anfc = parseInt(config.get("sysInfo.anfc"))
    if (anfc & 1 == 1) {
        driver.pwm.beep(config.get('sysInfo.beepd'), null, 1)
    }
    log.info('The final card swipe output data is', cardId);
    let nfcReport = config.get("sysInfo.nfcReport")
    if (nfcReport === 0 && config.get('sysInfo.w_mode') == 2) {
        //Turn off reporting and it will end immediately.
        return
    }
    // safeService.open()
    //safeService.openDoorByTime(100 * 50);
    driver.passage.beforeReport({ source: 'nfc', data: cardId })
}

//Check if it is a hexadecimal string; otherwise, skip.
function isHexadecimal(str) {
    // Use regular expressions to match the format of a hexadecimal string, specifically strings consisting of 0-9, a-f, and A-F.
    const hexRegex = /^[0-9a-fA-F]+$/;
    return hexRegex.test(str);
}

//4. Direct Card Number Processing Method
function fourHandle(cardNumber, start, length) {
    start = start > 4 ? 4 : start
    length = length > 4 ? 4 : length
    let startChar = (start - 1) * 2; // Convert the byte start position to a character index.
    let lengthInChars = length * 2;  // Convert byte length to character count

    // Special handling: The rule for starting position 4, and special cases with lengths from 1 to 4.
    if (start === 4) {
        if (length === 1) {
            return cardNumber.substring(startChar, startChar + 2); // When the length is 1, simply take "40".
        } else {
            // Loop through the output from the beginning.
            startChar = 0; // Start from the beginning
            lengthInChars = length * 2; // Calculate the correct number of characters
        }
    }

    return cardNumber.substring(startChar, startChar + lengthInChars);
}
export default nfcService
